/*
 *  Project:            timelyRV_v1.4.x -- a RISCV-32IMC SoC.
 *  Module name:        Testbench.
 *  Description:        Testbench of timelyRV_SoC_hardware.
 *  Last updated date:  2022.10.10.
 *
 *  Copyright (C) 2021-2022 Junnan Li <lijunnan@nudt.edu.cn>.
 *  Copyright and related rights are licensed under the MIT license.
 *
 */

`timescale 1ns/1ps
module Testbench_wrapper(
);

`ifdef DUMP_FSDB
  initial begin
    $fsdbDumpfile("wave.fsdb");
    $fsdbDumpvars(0,Testbench_wrapper);
    $fsdbDumpMDA();
  end
`endif
  reg                   clk,rst_n;

  wire                  rgmii_rxc;
  wire  [3:0]           rgmii_rd;
  wire                  rgmii_rx_ctl;
  wire  [3:0]           rgmii_td,rgmii_td_1;
  wire                  rgmii_tx_ctl,rgmii_tx_ctl_1;
  wire                  rgmii_txc,rgmii_txc_1;

  wire                  w_pktData_valid_gmii;
  wire  [133:0]         w_pktData_gmii;
  reg                   r_pktData_valid_um;
  reg   [133:0]         r_pktData_um;

  Network_Tester_Top Network_Tester_Top(
    .sys_clk            (clk              ),
    .rst_n              (rst_n            ),

    .mdio_mdc           (                 ),
    .mdio_mdio_io       (                 ),
    .phy_reset_n        (                 ),
    .rgmii_rd           (rgmii_rd         ),
    .rgmii_rx_ctl       (rgmii_rx_ctl     ),
    .rgmii_rxc          (rgmii_rxc        ),
    .rgmii_td           (rgmii_td         ),
    .rgmii_tx_ctl       (rgmii_tx_ctl     ),
    .rgmii_txc          (rgmii_txc        ),
    
    .mdio_mdc_1         (                 ),
    .mdio_mdio_io_1     (                 ),
    .phy_reset_n_1      (                 ),
    .rgmii_rd_1         (0                ),
    .rgmii_rx_ctl_1     (0                ),
    .rgmii_rxc_1        (0                ),
    .rgmii_td_1         (rgmii_td_1       ),
    .rgmii_tx_ctl_1     (rgmii_tx_ctl_1   ),
    .rgmii_txc_1        (rgmii_txc_1      ),

    .mdio_mdc_2         (                 ),
    .mdio_mdio_io_2     (                 ),
    .phy_reset_n_2      (                 ),
    .rgmii_rd_2         (rgmii_td_1       ),
    .rgmii_rx_ctl_2     (rgmii_tx_ctl_1   ),
    .rgmii_rxc_2        (rgmii_txc_1      ),
    .rgmii_td_2         (                 ),
    .rgmii_tx_ctl_2     (                 ),
    .rgmii_txc_2        (                 ),

    .mdio_mdc_3         (                 ),
    .mdio_mdio_io_3     (                 ),
    .phy_reset_n_3      (                 ),
    .rgmii_rd_3         (0                ),
    .rgmii_rx_ctl_3     (0                ),
    .rgmii_rxc_3        (0                ),
    .rgmii_td_3         (                 ),
    .rgmii_tx_ctl_3     (                 ),
    .rgmii_txc_3        (                 ),
    
    .uart_rx            (1'b1             ),
    .uart_tx            (                 ),
    .uart_cts           (1'b1             ),
    .uart_rts           (                 ),
    .uart_rx_1          (1'b1             ),
    .uart_tx_1          (                 ),
    .uart_cts_1         (1'b1             ),
    .uart_rts_1         (                 )
  );

  soc_runtime runtime_conf(
    .clk_125m             (clk                          ),
    .sys_rst_n            (rst_n                        ),
    //* rgmii input;
    .rgmii_rd             (rgmii_td                     ),  //* input
    .rgmii_rx_ctl         (rgmii_tx_ctl                 ),  //* input
    .rgmii_rxc            (rgmii_txc                    ),  //* input
    //* rgmii output;
    .rgmii_txc            (rgmii_rxc                    ),  //* output
    .rgmii_td             (rgmii_rd                     ),  //* output
    .rgmii_tx_ctl         (rgmii_rx_ctl                 ),  //* output
    //* um;
    .pktData_valid_gmii   (w_pktData_valid_gmii         ),
    .pktData_gmii         (w_pktData_gmii               ),
    .pkt_length_gmii      (                             ),
    .ready_in             (1'b1                         ),
    .pktData_valid_um     (r_pktData_valid_um           ),
    .pktData_um           (r_pktData_um                 ),
    //* crc;
    .i_crc_toCheck_enable (1'b0                         ),
    .i_crc_toCheck        (32'b0                        ),
    .o_crc_sendPkt        (                             )
  );

  
  initial begin
    rst_n = 0;
    #200  rst_n = 1;
  end
  initial begin
    clk = 0;
    forever #4 clk = ~clk;
  end
  initial begin
    #200000 $finish;
  end
  
  reg [15:0]    cnt_clk;
  reg [3:0]     state_conf;
  localparam    IDLE_S            = 4'd0,
                CONF_PKT_S        = 4'd1,
                SET_INTERNAL_CNT  = 4'd2,
                START_SEND_S      = 4'd3,
                WAIT_S            = 4'd4;


  always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
      state_conf                  <= IDLE_S;
      r_pktData_valid_um          <= 1'b0;
      r_pktData_um                <= 134'b0;
      cnt_clk                     <= 16'b0;
    end
    else begin
      case(state_conf)
        IDLE_S: begin
          cnt_clk                 <= cnt_clk + 16'd1;
          if(cnt_clk[8] == 1'b1) begin
            cnt_clk               <= 16'b0;
            state_conf            <= CONF_PKT_S;
          end
        end
        CONF_PKT_S: begin
          cnt_clk                 <= cnt_clk + 16'd1;
          r_pktData_valid_um      <= 1'b1;
          if(cnt_clk[15:1] == 15'b0) begin
            case(cnt_clk[0])
              1'd0: r_pktData_um  <= {2'b01,4'hf,48'h0102,48'h8988,16'h9004,16'h02};
              1'd1: r_pktData_um  <= {2'b00,4'hf,32'h1,32'h2,32'h3,32'h4};
            endcase
          end 
          else begin
            r_pktData_um          <= {2'b0,4'hf, (r_pktData_um[96+:32]+32'd1),
                                      (r_pktData_um[64+:32]+32'd1),
                                      (r_pktData_um[32+:32]+32'd1),
                                      (r_pktData_um[0+:32]+32'd1)};
          end
          
          if(cnt_clk[3:0] == 4'hf) begin
            r_pktData_um          <= {2'b10,4'hf, (r_pktData_um[96+:32]+32'd1),
                                      (r_pktData_um[64+:32]+32'd1),
                                      (r_pktData_um[32+:32]+32'd1),
                                      (r_pktData_um[0+:32]+32'd1)};
          end
          if(cnt_clk[4] == 1'h1) begin
            r_pktData_valid_um    <= 1'b0;
            cnt_clk               <= 16'b0;
            state_conf            <= SET_INTERNAL_CNT;
          end
        end
        SET_INTERNAL_CNT: begin
          cnt_clk                 <= cnt_clk + 16'd1;
          r_pktData_valid_um      <= 1'b1;
          case(cnt_clk[1:0])
            2'd0: r_pktData_um    <= {2'b01,4'hf,48'h0102,48'h8988,16'h9004,16'h04};
            2'd1: r_pktData_um    <= {2'b00,4'hf,32'h0,32'h0,32'h0,16'd400,16'h0};
            2'd2: r_pktData_um    <= {2'b00,4'hf, 128'b0};
            2'd3: r_pktData_um    <= {2'b10,4'hf, 128'b0};
          endcase
          
          if(cnt_clk[2] == 1'h1) begin
            r_pktData_valid_um    <= 1'b0;
            cnt_clk               <= 16'b0;
            state_conf            <= START_SEND_S;
          end
        end
        START_SEND_S: begin
          cnt_clk                 <= cnt_clk + 16'd1;
          r_pktData_valid_um      <= 1'b1;
          case(cnt_clk[1:0])
            2'd0: r_pktData_um    <= {2'b01,4'hf,48'h0102,48'h8988,16'h9004,16'h0};
            2'd1: r_pktData_um    <= {2'b00,4'hf,32'h0,32'h0,32'h0,32'h0};
            2'd2: r_pktData_um    <= {2'b00,4'hf, 128'b0};
            2'd3: r_pktData_um    <= {2'b10,4'hf, 128'b0};
          endcase
          
          if(cnt_clk[2] == 1'h1) begin
            r_pktData_valid_um    <= 1'b0;
            cnt_clk               <= 16'b0;
            state_conf            <= WAIT_S;
          end
        end
        WAIT_S: begin
          state_conf              <= WAIT_S;
        end
        default: begin
          state_conf              <= IDLE_S;
        end
      endcase
    end
  end

endmodule
